"""
This module lets you install a signal handler that invokes the debugger when
you press Ctrl+C.
"""

import sys
import signal
import pdb

def launch_debugger_on_uncaught_exception():
    old_excepthook = sys.excepthook

    def excepthook(exception_class, exception_value, traceback_object):
        old_excepthook(exception_class, exception_value, traceback_object)
        # TODO: If the exception occurred in a different thread and the mean
        #       thread is still blocked, pdb won't start up.  You can break
        #       into the main thread, but pdb doesn't seem to let you switch
        #       between threads.
        pdb.post_mortem(traceback_object)

    sys.excepthook = excepthook

def listen_for_keyboard_interrupt():
    """Install a signal handler that invokes the debugger when the user presses
    Ctrl+C.
    """
    signal.signal(signal.SIGINT, _handle_keyboard_interrupt)

def _handle_keyboard_interrupt(signal_number, interrupted_frame):
    # Restore the default signal handler so the user can kill the process
    # by hitting Ctrl-C twice.
    signal.signal(signal.SIGINT, signal.SIG_DFL)

    try:
        pdb.set_trace()
    finally:
        listen_for_keyboard_interrupt()

if __name__ == "__main__":
    launch_debugger_on_uncaught_exception()
    listen_for_keyboard_interrupt()

